package com.util.file;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.util.excel.FileUtilH;
import com.util.excel.Listener;
import com.util.thred.ThreadUtil;

import java.io.File;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * @Description: 对文件进行排序
 * new SortFile("D:\\temp\\2405\\4月\\低流量.csv",9,0);
 * @Author: hechaobo
 * @Date: 2024/5/15
 **/
public class SortFile {

    String tempPath = "/temp/sort/";
    String path;
    int[] idx;
    private LinkedList<String> filePath = new LinkedList<>();//被拆分的文件结果
    ThreadUtil threadUtil = new ThreadUtil(5);

    /**
     * @param path 文件名
     * @param idx  排序列下标
     */
    public SortFile(String path, int... idx) {
        this.path = path;
        this.idx = idx;
        sort1();
        while (threadUtil.getSemaphore().availablePermits()!=5) {
        }
        merge(filePath);
        threadUtil.shutdown();
    }

    //获取拆分的文件，并将其合并
    public void merge(LinkedList<String> filePath) {
        if (filePath.size() == 1) return;
        LinkedList<String> resPath = new LinkedList<>();
        List<Runnable> runnables = new ArrayList<>();
        while (filePath.size() > 1) {
            String path1 = filePath.remove();
            String path2 = filePath.remove();
            String res = tempPath + "合并后" + RandomUtil.randomInt(10000) + ".csv";
            runnables.add(() -> {
                SortLine sortLine = new SortLine(path1, path2,
                        res, idx);
                sortLine.invoke();
                resPath.add(res);
                FileUtil.del(path1);
                FileUtil.del(path2);
            });

        }
        ThreadUtil.runWorks(runnables);
        if (filePath.size() == 1) {
            resPath.add(filePath.remove());
        }
        merge(resPath);
    }

    public void sort1() {
        File file = new File(path);
        String name = file.getName().replace(".csv", "");
        FileUtilH.read(path, new Listener() {
            List<String> head;
            List<List<String>> data = new LinkedList<>();

            @Override
            public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
                head = ListUtil.toList(headMap.values());
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                sortAndWrite(data);
            }

            private void sortAndWrite(List<List<String>> list) {
                threadUtil.doWork(() -> {
                    list.sort((a, b) -> {
                        int i = 0;
                        for (int index : idx) {
                            if (a.get(index) == null) {
                                i = -1;
                            } else if (b.get(index) == null) {
                                i = 1;
                            } else {
                                i = a.get(index).compareTo(b.get(index));
                            }
                            if (i != 0) {
                                return i;
                            }
                        }
                        return i;
                    });
                    list.add(0, head);
                    String pathName = tempPath + name + "sort" + n++ + ".csv";
                    filePath.add(pathName);
                    EasyExcel.write(pathName).sheet().doWrite(list);
                });
            }

            int n = 0;

            @Override
            public void invoke(Map<Integer, String> integerStringMap, AnalysisContext analysisContext) {
                data.add(ListUtil.toList(integerStringMap.values()));
                if (data.size() == 300000) {
                    sortAndWrite(data);
                    data = new LinkedList<>();
                }
            }
        });
    }

    public void sort2() {
        File file = new File(path);
        String name = file.getName().replace(".csv", "");
        FileUtilH.read(path, new Listener() {
            List<String> head;
            List<List<String>> data = new LinkedList<>();

            @Override
            public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
                head = ListUtil.toList(headMap.values());
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                sortAndWrite(data);
            }

            private void sortAndWrite(List<List<String>> list) {
                list.sort((a, b) -> {
                    int i = 0;
                    for (int index : idx) {
                        i = a.get(index).compareTo(b.get(index));
                        if (i != 0) {
                            return i;
                        }
                    }
                    return i;
                });
                list.add(0, head);
                String pathName = tempPath + name + "sort" + n++ + ".csv";
                filePath.add(pathName);
                EasyExcel.write(pathName).sheet().doWrite(list);
            }

            int n = 0;

            @Override
            public void invoke(Map<Integer, String> integerStringMap, AnalysisContext analysisContext) {
                data.add(ListUtil.toList(integerStringMap.values()));
                if (data.size() == 800000) {
                    sortAndWrite(data);
                    data = new LinkedList<>();
                }
            }
        });
    }
}
